package com.sg.bars.server.kernel.service;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.sg.bars.client.kernel.action.ActionException;
import com.sg.bars.server.kernel.dao.JpaDao;

/**
 * @author Semyon Goryachkin
 *
 */
class DataServiceCoreImpl implements DataServiceCore{
	private static final long serialVersionUID = 6367931078528095151L;

	protected final Logger logger = LoggerFactory.getLogger(getClass());
	
	private JpaDao jpaDao;
	
	public JpaDao getJpaDao() {
		return jpaDao;
	}

	@Required
	public void setJpaDao(JpaDao jpaDao) {
		this.jpaDao = jpaDao;
	}
	
	@Transactional(propagation=Propagation.REQUIRED, readOnly=false, rollbackFor={ActionException.class})
	public Object doActionQueryTransactionalRequired(AbstractActionQuery actionQuery, ActionQueryRunner dataServiceQuery) throws ActionException{
		return doActionQuery(actionQuery, dataServiceQuery);
	}
	
	@Transactional(propagation=Propagation.REQUIRED, readOnly=true, rollbackFor={ActionException.class})
	public Object doActionQueryTransactionalRequiredReadOnly(AbstractActionQuery actionQuery, ActionQueryRunner dataServiceQuery) throws ActionException{
		return doActionQuery(actionQuery, dataServiceQuery);
	}
	
	public Object doActionQueryUnTransactional(AbstractActionQuery actionQuery, ActionQueryRunner dataServiceQuery) throws ActionException{
		return doActionQuery(actionQuery, dataServiceQuery);
	}
	
	public Object doActionQuery(AbstractActionQuery actionQuery, ActionQueryRunner dataServiceQuery) throws ActionException{
		if (logger.isDebugEnabled()){
			logger.debug("Action {} runs ActionQuery {}. TransactionalConfig: {}", new Object[]{actionQuery.getAction(), actionQuery, actionQuery.getTransactionalConfig()});
		}
		if (actionQuery.getPreActionQuery()!=null){
			AbstractActionQuery preActionQuery = actionQuery.getPreActionQuery();
			preActionQuery.setJpaDao(getJpaDao());
			actionQuery.setPreResult(dataServiceQuery.doActionQuery(actionQuery.getPreActionQuery()));
		}
		actionQuery.setJpaDao(getJpaDao());
		Object result = actionQuery.processQuery();
		if (actionQuery.getPostActionQuery()!=null){
			AbstractActionQuery postActionQuery = actionQuery.getPostActionQuery();
			postActionQuery.setJpaDao(getJpaDao());
			dataServiceQuery.doActionQuery(actionQuery.getPostActionQuery());
		}
		if (logger.isDebugEnabled()){
			logger.debug("Action {} end", actionQuery.getAction());
		}
		return result;
	}
	
}
